/*
 * DataUtiliity.java
 *
 * Created on 22 dicembre 2004, 16.25
 */

package org.stars.util;

import java.sql.Timestamp;
import java.util.Date;

import org.joda.time.DateMidnight;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;

/**
 * Classe d'utilità per le date.
 * 
 * @author Francesco Benincasa (908099)
 */
public abstract class DateUtility {
    
	/**
	 * Restuisce la data attuale, compresa di ore e minuti.
	 * 
	 * @return data attuale.
	 */
	public static Timestamp getNow() {
		return (new Timestamp((new Date().getTime())));
	}
	
	/**
	 * Converte una data in una stringa definendone il formato. Un esempio
	 * tipico di formato è <code>dd/MM/yyyy</code>.
	 * 
	 * @param date
	 *            data da formattare
	 * 
	 * @param format
	 *            formato da applicare
	 * 
	 * @return stringa che rappresenta la data formattata
	 * 
	 */
	public static String convertDateToString(Date date, String format) {
		
		if (date != null)
		{
			DateTimeFormatter dtf=DateTimeFormat.forPattern(format);
			return dtf.print(date.getTime());			
		}
		return null;
	}

	/**
	 * Converte una data in una stringa nel formato <code>dd/MM/yyyy</code>.
	 * 
	 * @param date
	 * 
	 * @return
	 * 		data sottoforma di stringa
	 */
	public static String convertDateToString(Date date) {
		return convertDateToString(date, "dd/MM/yyyy");
	}

	
	/**
	 * Converte un oggetto di tipo data in timeStamp.
	 * @param date
	 * @return
	 * 		timestamp
	 */
	public static Timestamp convertDateToTimestamp(Date date) {
		Timestamp ret=new Timestamp(date.getTime());
		
		return ret;
	}
	
	/**
	 * Converte un oggetto di tipo timeStamp in uno di tipo data.
	 * @param timeStamp
	 * @return
	 * 		data
	 */
	public static Date convertTimeStampToDate(Timestamp timeStamp) {
		Date ret=new Date(timeStamp.getTime());
		
		return ret;
	}
 	
	

	/**
	 * Converte una data in una stringa nel formato passato come argomento.
	 * 
	 * @param
	 * 		date
	 * @param
	 * 		format
	 * @return
	 * 		date
	 */
	public static Date convertStringToDate(String date, String format) {		
		try {
			
			if (date != null)
			{
				DateTimeFormatter dtf=DateTimeFormat.forPattern(format);
				DateTime dt=dtf.parseDateTime(date);
				return dt.toDate();			
			}									
		} catch (Exception e) {
		}
		return null;
	}
	
	/**
	 * Restituisce il formato usato per la codifica.
	 * 
	 * @return
	 * 		formato
	 */
	public static String getDateAndTimeFormat()
	{
		return "dd/MM/yyyy HH:mm.ss";
	}
	
	/**
	 * Converte una data in una stringa nel formato 'dd/MM/yyyy'.
	 * 
	 * @param
	 * 		date
	 * @return
	 * 		date
	 */
	public static Date convertStringToDate(String date) {
		return getOnlyDate(convertStringToDate(date,"dd/MM/yyyy"));
	}
	
	/**
	 * Converte una data in una stringa nel formato 'dd/MM/yyyy'.
	 * 
	 * @param
	 * 		date
	 * @return
	 * 		date
	 */
	public static Date toDate(String date) {
		return getOnlyDate(convertStringToDate(date,"dd/MM/yyyy"));
	}
	
	/**
	 * Converte una data in formata stringa (dd/MM/yyyy) nel timestamp.
	 * 
	 * @param
	 * 		date
	 * @return
	 * 		date
	 */
	public static Timestamp toTimeStamp(String date) {
		Date data=convertStringToDate(date,"dd/MM/yyyy");
		return new Timestamp(data.getTime());
	}
	
	/**
	 * Converte una data in una stringa nel formato dd/MM/yyyy.
	 * Alias del metodo convertDateToString().
	 * 
	 * @see #convertDateToString(Date)
	 * @param
	 * 		data
	 * @return
	 * 		data
	 */
	public static String toString(Date data) {
		return convertDateToString(data);
	}

	/**
	 * <p>
	 * Data una data, la restituisce impostando a 0, l'ora, i minuti, i secondi
	 * ed i millisecondi.
	 * </p>
	 * <p>
	 * La versione precedente utilizzava il GregorianCalendar.
	 * </p>
	 * 
	 * @param
	 * 		date
	 * @return
	 * 		data senza informazioni sull'ora
	 */
	public static Date getOnlyDate(Date date) {
		
		if (date==null) return null; // FRR gestito caso di mancanza della data
		
		DateMidnight dm=new DateMidnight(date.getTime());		
		
		return dm.toDate();				
	}
	
	/**
	 * <p>
	 * Data un timestamp, la restituisce impostando a 0, l'ora, i minuti, i secondi
	 * ed i millisecondi.
	 * </p>
	 * <p>
	 * La versione precedente utilizzava il calendar
	 * </p>
	 * 
	 * @param
	 * 		date
	 * @return
	 * 		timestamp senza informazioni sull'ora
	 */
	public static Timestamp getOnlyDate(Timestamp date) {
		if (date==null) return null; // FRR gestito caso di mancanza della data
		
		DateMidnight dm=new DateMidnight(date.getTime());		
		
		return new Timestamp(dm.getMillis());
	}
	
	
	/**
	 * <p>
	 * Data una data ed una quantita' di giorni positiva o negativa, calcola la
	 * data che si ottiene dalla data di partenza pi� i giorni passati come
	 * argomento.<br>
	 * 
	 * @param dt
	 *            data di partenza
	 * 
	 * @param ds
	 *            giorni da aggiungere o sottrarre
	 * 
	 * @return data risultato della somma
	 */
	public static Date cambioGiorno(Date dt, int ds) {
		if (dt==null) return null; // FRR gestito caso di mancanza della data
		
		DateTime dm=new DateTime(dt.getTime());
		dm=dm.plusDays(ds);		
		return dm.toDate();
	}
	
	/**
	 * <p>
	 * Data una data ed una quantità di giorni positiva o negativa, calcola la
	 * data che si ottiene dalla data di partenza più i giorni passati come
	 * argomento.<br>
	 * 
	 * @param dt
	 *            data di partenza
	 * @param ds
	 *            giorni da aggiungere o sottrarre
	 * 
	 * @return data risultato della somma
	 */
	public static Timestamp cambioGiorno(Timestamp dt, int ds) {
		if (dt==null) return null; // FRR gestito caso di mancanza della data
		
		DateTime dm=new DateTime(dt.getTime());
		dm=dm.plusDays(ds);		
		return new Timestamp(dm.getMillis());
	}
	
	/**
	 * Confronta due date per vedere se sono uguali. Restituisce <code>true</code> se
	 * entrambe sono null o contengono la stessa data. <b>Il confronto viene fatto tenendo conto anche
	 * delle ore, minuti e secondi</b>.
	 * 
	 * @param data1
	 * @param data2
	 * @return
	 * 		<code>true</code> se le due dati sono uguali, <code>false</code> altrimenti
	 */
	public static boolean equals(Date data1, Date data2)
	{		
		if (data1==null && data2==null) return true;
		
		if (
				(data1!=null && data2==null)
				||
				(data1==null && data2!=null)
			)
		return false;
		
		return (data1.compareTo(data2)==0);				
	}
	
	/**
	 * Confronta due date per vedere se sono uguali. Restituisce <code>true</code> se
	 * entrambe sono null o contengono la stessa data. <b>Il confronto viene fatto tenendo conto SOLO 
	 * della data</b>.
	 * 
	 * @param data1
	 * @param data2
	 * @return
	 * 		<code>true</code> se le due dati sono uguali, <code>false</code> altrimenti
	 */
	public static boolean equalsDate(Date data1, Date data2)
	{				
		return compareTo(data1,data2)==0;				
	}
	
	/**
	 * Effettua un confronto tra due date. <b>Il confronto viene fatto tenendo conto SOLO della
	 * data e scartando le informazioni relative alle ore, minuti e secondi</b>.
	 * <ul>
	 * <li>Se le due date sono <i>null</i> restituisce 0. </li>
	 * <li>Se il primo parametro è <i>null</i> e l'altro è una data valida, restituisce -1</li>
	 * <li>Se il secondo parametro è <i>null</i> e l'altro è una data valida, restituisce 1</li>
	 * <li>Se le due date sono valide, viene restituito il confronto tra le due date</li>
	 * </ul>
	 * 
	 * @param data1
	 * 		prima data 
	 * @param data2
	 * 		seconda data
	 * 
	 * @return
	 * <ul>
	 * <li>Se le due date sono <i>null</i> restituisce 0. </li>
	 * <li>Se il primo parametro è <i>null</i> e l'altro è una data valida, restituisce -1</li>
	 * <li>Se il secondo parametro è <i>null</i> e l'altro è una data valida, restituisce 1</li>
	 * <li>Se le due date sono valide, viene restituito il confronto tra le due date</li>
	 * </ul>
	 */
	public static int compareTo(Date data1, Date data2)
	{
		if (data1==null && data2==null) return 0;
		
		if (data1!=null && data2==null)
		{
			return -1;
		}
		else if (data1==null && data2!=null)
		{
			return +1;
		}
		
		data1=getOnlyDate(data1);
		data2=getOnlyDate(data2);
		
		return data1.compareTo(data2);
	}
	
	/**
	 * Verifica se la data <code>value</code> rientra nell'intervallo definito dagli due parametri <code>lowlimit</code> e
	 *  <code>highlimit</code>. Il confronto viene effettuato prendendo in considerazione solo le date, le ore, minuti e secondi non
	 *  vengono considerati. Le date che definiscono i limiti dell'intervallo sono incluse nello stesso. Se l'intervallo risulta essere aperto superiormente o inferiormente la data viene confrontata
	 *  solo con il limite definito. Di seguito riportiamo alcuni valori di esempio e i risultati ottenuti applicandoli
	 *  alla funzione.
	 * 
	 * <br><br>
	 * <table border=1>
	 * <tr><td><b>value</b></td><td><b>low</b></td><td><b>high</b></td><td><b>result</b></td></tr>
	 *  <tr><td>           null                    </td><td>			null					</td><td>			null				 </td><td>	false</td></tr>
	 *  <tr><td>           null                    </td><td>			null					</td><td>	20/02/2006</td><td> 	false</td></tr>
	 *  <tr><td>           null                    </td><td>	01/02/2006	</td><td>	null						  </td><td> 	<b><code>true</code></b></td></tr>
	 *  <tr><td>   21/02/2006  </td><td>   01/02/2006	</td><td>	20/02/2006</td><td> 	false</td></tr>				
	 *  <tr><td>   01/02/2006  </td><td>	01/02/2006	</td><td>	20/02/2006</td><td> 	<b><code>true</code></b></td></tr>
	 *  <tr><td>   20/02/2006  </td><td>	01/02/2006	</td><td>	20/02/2006</td><td> 	<b><code>true</code></b></td></tr>
	 *  <tr><td>   21/02/2006  </td><td>	01/02/2006	</td><td>	20/02/2006</td><td> 	false</td></tr>
	 *  <tr><td>   10/02/2006  </td><td>	01/02/2006	</td><td>	20/02/2006</td><td> 	<b><code>true</code></b></td></tr>
	 *  <tr><td>   01/01/2006  </td><td>	01/02/2006	</td><td>	20/02/2006</td><td> 	false</td></tr>
	 *  <tr><td>   01/02/2006  </td><td>			null					</td><td>	20/02/2006</td><td> 	<b><code>true</code></b></td></tr>
	 *  <tr><td>   01/03/2006  </td><td>			null					</td><td>	20/02/2006</td><td> 	false</td></tr>
	 *  <tr><td>   10/02/2006  </td><td>	01/02/2006	</td><td>		null					  </td><td> 	<b><code>true</code></b></td></tr>
	 *  <tr><td>   01/01/2006  </td><td>	01/02/2006	</td><td>		null					  </td><td> 	false</td></tr>
	 *  <tr><td>   01/02/2006  </td><td>			null					</td><td>		null					  </td><td> 	false</td></tr>
	 *  </table>	
	 *  <br>
	 * @param value
	 * 		valore da confrontare
	 * @param lowLimit
	 * 		limite inferiore dell'intervallo
	 * @param highLimit
	 * 		limite superiore dell'intervallo
	 * @return
	 * 		<code>true</code> se la data rientra nell'intervallo. <code>false</code> altrimenti.
	 */
	public static boolean between(Date value, Date lowLimit, Date highLimit)
	{		
		if (lowLimit!=null && highLimit==null && value==null) return true;
		
		if (value==null) return false;
		if (lowLimit==null && highLimit==null) return false;				
		
		value		=	getOnlyDate(value);
		lowLimit	=	getOnlyDate(lowLimit);
		highLimit	=	getOnlyDate(highLimit);
		
		if (lowLimit==null && highLimit!=null)
		{
			return (highLimit.compareTo(value)>=0);
		}
		
		if (lowLimit!=null && highLimit==null)
		{
			return (lowLimit.compareTo(value)<=0);
		}
		
		return (lowLimit.compareTo(value)<=0) && (highLimit.compareTo(value)>=0);	
	}
	
		        
    /**
     * Restuisce l'ora e la data attuale sotto forma di stringa nel formato
     * <i>yyyy/mm/dd</i>. Ad esempio per il giorno 25 febbraio 2005 restituisce 
     * la stringa "2005/02/21".
     * 
     * La versione precedente lavorava con il calendar
     *
     * @return
     * 		data attuale sotto forma di stringa nel formato <i>yyyy/mm/dd</i>
     */
    public static String getStringYYYYMMDD() {
        String app = "";
        
        DateTime dt=new DateTime();
        
        app += String.valueOf(dt.getYear())+"/";
        app += StringUtility.fillUp(String.valueOf(dt.getMonthOfYear()),2,false,'0')+"/" ;
        app += StringUtility.fillUp(String.valueOf(dt.getDayOfMonth()),2,false,'0');
        
        return app;
    }
    
    /**
     * Restuisce l'ora e la data attuale sotto forma di int nel formato
     * <i>yyyy/mm/dd</i>. Ad esempio per il giorno 25 febbraio 2005 restituirebbe
     * l'intero 20050221.
     * 
     * Prima lavorava con CAlendar
     *
     * @return
     * 		data attuale sotto forma di stringa nel formato <i>yyyy/mm/dd</i>
     */
    public static int getIntYYYYMMDD() {
        int app = 0;
        
        DateTime dt=new DateTime();
        app += dt.getYear()*10000;
        app += dt.getMonthOfYear()*100;
        app += dt.getDayOfMonth();
               
        
        return app;
    }
    
    /**
     * Restuisce la data attuale sotto forma di int nel formato
     * <i>yyyy/mm</i>. Ad esempio per il giorno 25 febbraio 2005 restituirebbe
     * l'intero 200502.
     * 
     * Prima lavorava con CAlendar
     *
     * @return
     * 		data attuale sotto forma di stringa nel formato <i>yyyymm</i>
     */
    public static int getIntYYYYMM() {
        int app = 0;
        
        DateTime dt=new DateTime();
        app += dt.getYear()*10000;
        app += dt.getMonthOfYear()*100;
        
        return app;
    }
    
    /**
     * Restuisce la data parametro sotto forma di int nel formato
     * <i>yyyy/mm</i>. Ad esempio per il giorno 25 febbraio 2005 restituirebbe
     * l'intero 200502.
     * 
     * @param date 
     * 		data da convertire
     * @return
     * 		data attuale sotto forma di stringa nel formato <i>yyyymm</i>
     */
    public static int getIntYYYYMM(Date date) {
        int app = 0;
        
        DateTime dt=new DateTime(date.getTime());
        app += dt.getYear()*10000;
        app += dt.getMonthOfYear()*100;        
        
        return app;
    }
    
    /**
     * Restuisce la data parametro sotto forma di int nel formato
     * <i>yyyy</i>. Ad esempio per il giorno 25 febbraio 2005 restituirebbe
     * l'intero 2005.
     * 
     * @param date 
     * 		data da convertire
     * @return
     * 		data attuale sotto forma di stringa nel formato <i>yyyy</i>
     */
    public static int getIntYYYY(Date date) {
    	int app=0;
    	
        DateTime dt=new DateTime(date.getTime());
        app = dt.getYear();               
        
        return app;
    }
    
    
    /**
     * Restituisce l'anno corrente sottoforma di numero
     * 
     * @return
     * 		intero contenente l'anno corrente
     */
    public static int getIntYYYY() {
    	int app=0;
    	
        DateTime dt=new DateTime();
        app = dt.getYear();               
        
        return app;
    }
    
    
    
}
